package protocol

import (
	"google.golang.org/protobuf/proto"
	"wths/wthsjy-im/protocol/protocolpb"
)

func NewConnectPacket(token string, reConnect bool) (*Packet, error) {
	info := &protocolpb.Connect{
		Token:     token,
		ReConnect: reConnect,
	}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(CONNECT, bs), nil
}

func DecodeConnect(bs []byte) (*protocolpb.Connect, error) {
	info := &protocolpb.Connect{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}
func NewDisConnectPacket(token string, reConnect bool) (*Packet, error) {
	info := &protocolpb.DisConnect{}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(DISCONNECT, bs), nil
}

func DecodeDisConnect(bs []byte) (*protocolpb.DisConnect, error) {
	info := &protocolpb.DisConnect{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func NewConnectAckPacket(success bool, errMsg string) (*Packet, error) {
	info := &protocolpb.ConnectAck{
		Success: success,
		ErrMsg:  errMsg,
	}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(ConnectAck, bs), nil
}

func DecodeConnectAck(bs []byte) (*protocolpb.ConnectAck, error) {
	info := &protocolpb.ConnectAck{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func NewPublishPacket(topicName string, data []byte) (*Packet, error) {
	info := &protocolpb.Publish{
		TopicName: topicName,
		Payload:   data,
	}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(PUBLISH, bs), nil
}

func DecodePublish(bs []byte) (*protocolpb.Publish, error) {
	info := &protocolpb.Publish{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func NewPingPacket() *Packet {
	info := &protocolpb.Ping{}
	bs, _ := proto.Marshal(info)
	return newPacket(PING, bs)
}

func DecodePing(bs []byte) (*protocolpb.Ping, error) {
	info := &protocolpb.Ping{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func NewSubAckPacket(mp map[string]bool) (*Packet, error) {
	info := &protocolpb.SubscribeAck{
		Acks: mp,
	}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(SubscribeAck, bs), nil
}

func DecodeSubAck(bs []byte) (*protocolpb.SubscribeAck, error) {
	info := &protocolpb.SubscribeAck{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func NewSubscribePacket(topicNames []string) (*Packet, error) {
	info := &protocolpb.Subscribe{
		TopicNames: topicNames,
	}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(Subscribe, bs), nil
}

func DecodeSubscribe(bs []byte) (*protocolpb.Subscribe, error) {
	info := &protocolpb.Subscribe{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func NewUnsubscribePacket(topicNames []string) (*Packet, error) {
	info := &protocolpb.Unsubscribe{
		TopicNames: topicNames,
	}
	bs, err := proto.Marshal(info)
	if err != nil {
		return nil, err
	}
	return newPacket(UnSubscribe, bs), nil
}

func DecodeUnsubscribe(bs []byte) (*protocolpb.Unsubscribe, error) {
	info := &protocolpb.Unsubscribe{}
	err := proto.Unmarshal(bs, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}
